package com.scuec.groupfive.service.impl;

import com.alibaba.fastjson.JSON;
import com.scuec.groupfive.entity.*;
import com.scuec.groupfive.mapper.QuestionMapper;
import com.scuec.groupfive.mapper.UserMockMapper;
import com.scuec.groupfive.service.ExamService;
import com.scuec.groupfive.vo.ExamPaperVO;
import com.scuec.groupfive.vo.ExamResultVO;
import com.scuec.groupfive.vo.QuestionDetailVO;
import com.scuec.groupfive.dto.ExamSubmitDTO;
import com.scuec.groupfive.dto.QuestionAnswerDTO;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.TypeReference;
import java.util.ArrayList;
import java.util.LinkedHashMap;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import com.scuec.groupfive.exception.BusinessException;

@Service
public class ExamServiceImpl implements ExamService {

    private static final Logger logger = LoggerFactory.getLogger(ExamServiceImpl.class);

    @Autowired
    private UserMockMapper userMockMapper; // 统一注入一个Mapper实例

    @Autowired
    private QuestionMapper questionMapper; // 注入QuestionMapper

    @Override
    public List<QuestionInfo> generateRandomExam(String examType, ExamStructure structure, Long userId) {
        // 使用标准结构而不是传入的structure
        ExamStructure standardStructure = getStandardExamStructure(examType);
        validateStructure(standardStructure);
        List<Integer> subjectIds = getSubjectIdsByExamType(examType);
        if (subjectIds.isEmpty()) throw new IllegalArgumentException("未找到对应考试类型的科目");

        // 根据考试类型获取typeId
        int typeId = getTypeIdByExamType(examType);

        List<QuestionInfo> allQuestions = new ArrayList<>();

        // 单选题按科目分布获取（示例分布）
        Map<String, Integer> singleChoiceDist = getSubjectDistributionForSingleChoice(examType);
        List<QuestionInfo> singleChoices = getQuestionsBySubjectDistribution(
                subjectIds, "single_choice", structure.getSingleChoiceCount(), singleChoiceDist, typeId
        );

        // 填空题按科目分布获取
        Map<String, Integer> fillBlankDist = getSubjectDistributionForFillBlank(examType);
        List<QuestionInfo> fillBlanks = getQuestionsBySubjectDistribution(
                subjectIds, "fill_in_the_blank", structure.getFillBlankCount(), fillBlankDist, typeId
        );

        // 主观题随机获取（不区分科目）
        List<QuestionInfo> subjectives = userMockMapper.findRandomQuestionsBySubjectAndType(
                subjectIds, "subjective", structure.getSubjectiveCount(), typeId
        );

        allQuestions.addAll(singleChoices);
        allQuestions.addAll(fillBlanks);
        allQuestions.addAll(subjectives);
        setQuestionSequence(allQuestions);
        printQuestionCounts(allQuestions, structure); // 打印数量校验

        return allQuestions;
    }

    // 新增方法：根据考试类型获取typeId
    // 修改getTypeIdByExamType方法，确保数三有对应的typeId
    private int getTypeIdByExamType(String examType) {
        if (examType == null || examType.trim().isEmpty()) {
            throw new IllegalArgumentException("考试类型不能为空");
        }

        // 确保exam_types表中有数三对应的记录
        Integer typeId = userMockMapper.findTypeIdByExamType(examType);
        if (typeId == null) {
            // 如果没有查询到，使用默认映射
            Map<String, Integer> typeIdMap = new HashMap<>();
            typeIdMap.put("数一", 1);
            typeIdMap.put("数二", 2);
            typeIdMap.put("数三", 3); // 确保数三有对应的typeId

            typeId = typeIdMap.get(examType);
            if (typeId == null) {
                throw new IllegalArgumentException("未知的考试类型: " + examType);
            }
        }
        return typeId;
    }

    // 修改后的通用方法：按科目分布获取题目
    private List<QuestionInfo> getQuestionsBySubjectDistribution(
            List<Integer> subjectIds,
            String questionType,
            int totalCount,
            Map<String, Integer> distribution,
            int typeId) {

        List<QuestionInfo> questions = new ArrayList<>();
        Map<String, Integer> subjectIdNameMap = getSubjectNameIdMap(subjectIds);

        // 按分布比例获取各科目题目
        distribution.forEach((subjectName, count) -> {
            Integer subjectId = subjectIdNameMap.get(subjectName);
            if (subjectId != null && count > 0) {
                // 保证传入的参数数量和类型与方法定义一致
                questions.addAll(userMockMapper.findRandomQuestionsBySubjectAndType(
                        Arrays.asList(subjectId), questionType, count, typeId
                ));
            }
        });

        // 补足不足数量（从所有科目随机获取）
        int missing = totalCount - questions.size();
        if (missing > 0) {
            // 保证传入的参数数量和类型与方法定义一致
            questions.addAll(userMockMapper.findRandomQuestionsBySubjectAndType(
                    subjectIds, questionType, missing, typeId
            ));
        }
        System.out.println("查询科目：" + subjectIds + ", 题型：" + questionType + ", 数量：" + totalCount);
        return questions;
    }

    @Override
    public List<QuestionInfo> generateWeaknessExam(String examType, ExamStructure structure, Long userId) {
        // 使用标准结构
        ExamStructure standardStructure = getStandardExamStructure(examType);
        // 1. 获取当前考试类型的科目ID和typeId
        List<Integer> subjectIds = getSubjectIdsByExamType(examType);
        int typeId = getTypeIdByExamType(examType);

        List<QuestionInfo> allQuestions = new ArrayList<>();

        // 2. 从错题本获取题目（按题型和考试类型过滤）
        List<QuestionInfo> wrongSingleChoices = userMockMapper.getWrongQuestionsByUserAndTypeAndExamType(
                userId, "single_choice", structure.getSingleChoiceCount(), typeId);
        List<QuestionInfo> wrongFillBlanks = userMockMapper.getWrongQuestionsByUserAndTypeAndExamType(
                userId, "fill_in_the_blank", structure.getFillBlankCount(), typeId);
        List<QuestionInfo> wrongSubjectives = userMockMapper.getWrongQuestionsByUserAndTypeAndExamType(
                userId, "subjective", structure.getSubjectiveCount(), typeId);

        // 3. 从薄弱知识点获取题目（同样按考试类型过滤）
        List<Integer> weakPointIds = getUserWeakKnowledgePoints(userId, subjectIds);
        if (!weakPointIds.isEmpty()) {
            int remainSingle = structure.getSingleChoiceCount() - wrongSingleChoices.size();
            int remainFill = structure.getFillBlankCount() - wrongFillBlanks.size();
            int remainSubjective = structure.getSubjectiveCount() - wrongSubjectives.size();

            List<QuestionInfo> weakSingleChoices = userMockMapper.getQuestionsByKnowledgePointsAndExamType(
                    weakPointIds, "single_choice", remainSingle, typeId);
            List<QuestionInfo> weakFillBlanks = userMockMapper.getQuestionsByKnowledgePointsAndExamType(
                    weakPointIds, "fill_in_the_blank", remainFill, typeId);
            List<QuestionInfo> weakSubjectives = userMockMapper.getQuestionsByKnowledgePointsAndExamType(
                    weakPointIds, "subjective", remainSubjective, typeId);

            wrongSingleChoices.addAll(weakSingleChoices);
            wrongFillBlanks.addAll(weakFillBlanks);
            wrongSubjectives.addAll(weakSubjectives);
        }

        // 4. 合并题目
        allQuestions.addAll(wrongSingleChoices);
        allQuestions.addAll(wrongFillBlanks);
        allQuestions.addAll(wrongSubjectives);

        // 5. 数量不足时用随机题补足（确保只补当前考试类型的题目）
        supplementQuestionsIfNeeded(
                allQuestions,
                examType,
                structure,
                structure.getSingleChoiceCount(),
                structure.getFillBlankCount(),
                structure.getSubjectiveCount(),
                typeId
        );

        // 6. 设置题目序号
        setQuestionSequence(allQuestions);

        return allQuestions;
    }

    @Override
    public List<QuestionInfo> generateHighFrequencyExam(String examType, ExamStructure structure, Long userId) {
        // 使用标准结构
        ExamStructure standardStructure = getStandardExamStructure(examType);
        // 基础参数校验
        if (structure == null) {
            throw new IllegalArgumentException("试卷结构参数不能为null");
        }
        if (examType == null || examType.trim().isEmpty()) {
            throw new IllegalArgumentException("考试类型不能为null或空");
        }

        logger.info("开始生成高频易错题试卷，考试类型: {}", examType);

        List<QuestionInfo> allQuestions = new ArrayList<>();
        int totalNeeded = structure.getSingleChoiceCount() + structure.getFillBlankCount() + structure.getSubjectiveCount();

        // 1. 获取当前考试类型的typeId
        int typeId = getTypeIdByExamType(examType);
        logger.info("考试类型: {}, 对应的typeId: {}", examType, typeId);

        // 2. 查询高频错题（带考试类型和题型过滤）
        logger.info("开始查询高频易错题，需要数量: {}", totalNeeded);
        List<QuestionInfo> highFreqQuestions = userMockMapper.getHighFrequencyQuestionsByType(
                null,
                totalNeeded * 2, // 获取比需要数量更多的题目，确保有足够的选择
                typeId
        );

        // 确保列表不为null
        if (highFreqQuestions == null) {
            highFreqQuestions = new ArrayList<>();
            logger.warn("高频易错题查询返回null，已初始化为空列表");
        }
        logger.info("查询到的高频易错题数量: {}", highFreqQuestions.size());

        // 3. 按题型分组（新增空值过滤）
        Map<String, List<QuestionInfo>> typedQuestions = highFreqQuestions.stream()
                .filter(Objects::nonNull)
                .filter(q -> q.getQuestionType() != null && !q.getQuestionType().isEmpty())
                .collect(Collectors.groupingBy(
                        QuestionInfo::getQuestionType,
                        Collectors.toList()
                ));
        logger.info("按题型分组结果: {}", typedQuestions.keySet());

        // 4. 按试卷结构提取各题型题目
        int singleChoiceCount = structure.getSingleChoiceCount();
        int fillBlankCount = structure.getFillBlankCount();
        int subjectiveCount = structure.getSubjectiveCount();

        // 安全获取子列表
        List<QuestionInfo> singleChoices = Optional.ofNullable(typedQuestions.get("single_choice"))
                .map(list -> getSafeSubList(list, singleChoiceCount))
                .orElse(Collections.emptyList());

        List<QuestionInfo> fillBlanks = Optional.ofNullable(typedQuestions.get("fill_in_the_blank"))
                .map(list -> getSafeSubList(list, fillBlankCount))
                .orElse(Collections.emptyList());

        List<QuestionInfo> subjectives = Optional.ofNullable(typedQuestions.get("subjective"))
                .map(list -> getSafeSubList(list, subjectiveCount))
                .orElse(Collections.emptyList());

        allQuestions.addAll(singleChoices);
        allQuestions.addAll(fillBlanks);
        allQuestions.addAll(subjectives);

        // 5. 数量不足时用同类型随机题补足
        supplementQuestionsIfNeeded(
                allQuestions,
                examType,
                structure,
                singleChoiceCount,
                fillBlankCount,
                subjectiveCount,
                typeId
        );

        // 6. 设置题目序号
        setQuestionSequence(allQuestions);
        return allQuestions;
    }

    // 辅助方法：安全获取子列表
    private List<QuestionInfo> getSafeSubList(List<QuestionInfo> list, int count) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        int end = Math.min(count, list.size());
        return list.subList(0, end);
    }


    @Override
    public List<QuestionInfo> generateCustomExam(String examType, ExamStructure structure, List<Integer> knowledgePoints) {
        logger.info("开始生成自定义试卷，考试类型: {}, 知识点: {}", examType, knowledgePoints);

        try {
            // 1. 验证知识点
            List<Integer> validSubjectIds = getSubjectIdsByExamType(examType);
            List<KnowledgePoint> allPoints = userMockMapper.getKnowledgePointsBySubjectIds(validSubjectIds);

            List<Integer> validPointIds = knowledgePoints.stream()
                    .filter(pointId -> allPoints.stream().anyMatch(p -> p.getPointId().equals(pointId)))
                    .collect(Collectors.toList());

            if (validPointIds.isEmpty()) {
                throw new IllegalArgumentException("选择的知识点不属于该考试类型的科目");
            }

            // 2. 获取标准结构（确保数三的主观题数量为8）
            ExamStructure standardStructure = getStandardExamStructure(examType);
            int typeId = getTypeIdByExamType(examType);

            // 3. 按题型区块获取题目（严格保持顺序）
            List<QuestionInfo> allQuestions = new ArrayList<>();

            // 3.1 单选题区块（10题）
            List<QuestionInfo> singleChoices = userMockMapper.getCustomQuestionsByKnowledgePoints(
                    validPointIds, "single_choice", standardStructure.getSingleChoiceCount(), typeId);
            supplementQuestionsByType(allQuestions, singleChoices, "single_choice",
                    standardStructure.getSingleChoiceCount(), validSubjectIds, typeId);

            // 3.2 填空题区块（6题）
            List<QuestionInfo> fillBlanks = userMockMapper.getCustomQuestionsByKnowledgePoints(
                    validPointIds, "fill_in_the_blank", standardStructure.getFillBlankCount(), typeId);
            supplementQuestionsByType(allQuestions, fillBlanks, "fill_in_the_blank",
                    standardStructure.getFillBlankCount(), validSubjectIds, typeId);

            // 3.3 主观题区块（数三8题，其他6题）
            List<QuestionInfo> subjectives = userMockMapper.getCustomQuestionsByKnowledgePoints(
                    validPointIds, "subjective", standardStructure.getSubjectiveCount(), typeId);
            supplementQuestionsByType(allQuestions, subjectives, "subjective",
                    standardStructure.getSubjectiveCount(), validSubjectIds, typeId);

            // 4. 设置题目序号（按合并后的顺序）
            setQuestionSequence(allQuestions);

            logger.info("试卷结构验证 - 单选: {}, 填空: {}, 主观: {}",
                    allQuestions.stream().filter(q -> "single_choice".equals(q.getQuestionType())).count(),
                    allQuestions.stream().filter(q -> "fill_in_the_blank".equals(q.getQuestionType())).count(),
                    allQuestions.stream().filter(q -> "subjective".equals(q.getQuestionType())).count());

            return allQuestions;
        } catch (Exception e) {
            logger.error("生成自定义试卷时出错", e);
            throw e;
        }
    }

    // 新增方法：获取标准考试结构
    private ExamStructure getStandardExamStructure(String examType) {
        ExamStructure structure = new ExamStructure();
        if ("数三".equals(examType)) {
            structure.setSingleChoiceCount(10);
            structure.setFillBlankCount(6);
            structure.setSubjectiveCount(8); // 数三的主观题数量为8
        } else {
            // 数一和数二使用相同的结构
            structure.setSingleChoiceCount(10);
            structure.setFillBlankCount(6);
            structure.setSubjectiveCount(6);
        }
        return structure;
    }

    // --------------------- 辅助方法重构 ---------------------

    /**
     * 按科目分布获取题目（通用方法）
     */


    /**
     * 获取用户薄弱知识点（示例逻辑：从错题关联知识点中统计）
     */
    private List<Integer> getUserWeakKnowledgePoints(Long userId, List<Integer> subjectIds) {
        List<Integer> weakPointIds = userMockMapper.getWeakKnowledgePointIdsByUser(userId);

        return weakPointIds.stream()
                .filter(pointId -> {
                    Integer subjectId = userMockMapper.getSubjectIdByPointId(pointId);
                    return subjectIds.contains(subjectId);
                })
                .collect(Collectors.toList());
    }

    /**
     * 题目数量补足通用方法
     */
    /**
     * 题目数量补足通用方法
     */
    private void supplementQuestionsIfNeeded(
            List<QuestionInfo> current,
            String examType,
            ExamStructure structure,
            int targetSingle,
            int targetFill,
            int targetSubjective,
            int typeId
    ) {
        // 计算需要补足的数量
        long currentSingle = current.stream()
                .filter(q -> "single_choice".equals(q.getQuestionType())).count();
        long currentFill = current.stream()
                .filter(q -> "fill_in_the_blank".equals(q.getQuestionType())).count();
        long currentSubjective = current.stream()
                .filter(q -> "subjective".equals(q.getQuestionType())).count();

        int neededSingle = Math.max(0, targetSingle - (int)currentSingle);
        int neededFill = Math.max(0, targetFill - (int)currentFill);
        int neededSubjective = Math.max(0, targetSubjective - (int)currentSubjective);

        // 获取科目ID（关联考试类型）
        List<Integer> subjectIds = getSubjectIdsByExamType(examType);

        // 随机题补足（关联questions表，使用typeId过滤）
        if (neededSingle > 0) {
            List<QuestionInfo> randomSingles = userMockMapper.findRandomQuestionsBySubjectAndType(
                    subjectIds, "single_choice", neededSingle, typeId
            );
            current.addAll(Optional.ofNullable(randomSingles).orElse(Collections.emptyList()));
        }
        if (neededFill > 0) {
            List<QuestionInfo> randomFills = userMockMapper.findRandomQuestionsBySubjectAndType(
                    subjectIds, "fill_in_the_blank", neededFill, typeId
            );
            current.addAll(Optional.ofNullable(randomFills).orElse(Collections.emptyList()));
        }
        if (neededSubjective > 0) {
            List<QuestionInfo> randomSubjectives = userMockMapper.findRandomQuestionsBySubjectAndType(
                    subjectIds, "subjective", neededSubjective, typeId
            );
            current.addAll(Optional.ofNullable(randomSubjectives).orElse(Collections.emptyList()));
        }
    }

    /**
     * 打印题目数量（调试用）
     */
    private void printQuestionCounts(List<QuestionInfo> questions, ExamStructure structure) {
        long singleCount = questions.stream().filter(q -> "single_choice".equals(q.getQuestionType())).count();
        long fillCount = questions.stream().filter(q -> "fill_in_the_blank".equals(q.getQuestionType())).count();
        long subjectiveCount = questions.stream().filter(q -> "subjective".equals(q.getQuestionType())).count();

        System.out.println("生成试卷统计：");
        System.out.println("单选题：" + singleCount + "/" + structure.getSingleChoiceCount());
        System.out.println("填空题：" + fillCount + "/" + structure.getFillBlankCount());
        System.out.println("主观题：" + subjectiveCount + "/" + structure.getSubjectiveCount());
        System.out.println("总题数：" + questions.size() + "/" + structure.getTotalQuestions());
    }

    // --------------------- 辅助方法 ---------------------

    private void validateStructure(ExamStructure structure) {
        if (structure.getSingleChoiceCount() < 0 ||
                structure.getFillBlankCount() < 0 ||
                structure.getSubjectiveCount() < 0) {
            throw new IllegalArgumentException("题型数量不能为负数");
        }
    }

    private Map<String, Integer> getSubjectDistributionForSingleChoice(String examType) {
        // 原有逻辑不变
        Map<String, Integer> distribution = new HashMap<>();
        switch (examType) {
            case "数一": case "数三":
                distribution.put("高等数学", 4);
                distribution.put("线性代数", 3);
                distribution.put("概率论与数理统计", 3);
                break;
            case "数二":
                distribution.put("高等数学", 7);
                distribution.put("线性代数", 3);
                break;
            default: throw new IllegalArgumentException("不支持的考试类型: " + examType);
        }
        return distribution;
    }

    private Map<String, Integer> getSubjectDistributionForFillBlank(String examType) {
        // 原有逻辑不变
        Map<String, Integer> distribution = new HashMap<>();
        switch (examType) {
            case "数一": case "数三":
                distribution.put("高等数学", 4);
                distribution.put("线性代数", 1);
                distribution.put("概率论与数理统计", 1);
                break;
            case "数二":
                distribution.put("高等数学", 5);
                distribution.put("线性代数", 1);
                break;
            default: throw new IllegalArgumentException("不支持的考试类型: " + examType);
        }
        return distribution;
    }

    private Map<String, Integer> getSubjectNameIdMap(List<Integer> subjectIds) {
        // 示例映射（需根据实际数据库查询优化）
        return subjectIds.stream().collect(Collectors.toMap(
                id -> {
                    switch (id) {
                        case 1: return "高等数学";
                        case 2: return "线性代数";
                        case 3: return "概率论与数理统计";
                        default: return "";
                    }
                },
                id -> id
        ));
    }

    private void setQuestionSequence(List<QuestionInfo> questions) {
        for (int i = 0; i < questions.size(); i++) {
            questions.get(i).setSequence(i + 1);
        }
    }

    @Override
    public List<Integer> getSubjectIdsByExamType(String examType) {
        // 修改为从数据库查询（需确保exam_types表和subjects表有关联）
        switch(examType) {
            case "数一":
                return Arrays.asList(1, 2, 3); // 高数、线代、概率
            case "数二":
                return Arrays.asList(1, 2);    // 高数、线代
            case "数三":
                return Arrays.asList(1, 2, 3); // 高数、线代、概率
            default:
                throw new IllegalArgumentException("无效的考试类型");
        }
    }

    @Override
    public List<KnowledgePoint> getKnowledgePointsBySubjects(List<Integer> subjectIds) {
        // 确保subjectIds不为空
        if (subjectIds == null || subjectIds.isEmpty()) {
            return Collections.emptyList();
        }

        // 根据科目ID查询知识点（需通过Mapper操作数据库）
        List<KnowledgePoint> allPoints = userMockMapper.getKnowledgePointsBySubjectIds(subjectIds);

        // 根据考试类型进一步过滤知识点
        return allPoints.stream()
                .filter(point -> {
                    // 数二不包含概率论知识点（subjectId=3）
                    if (subjectIds.size() == 2 && !subjectIds.contains(3)) {
                        return point.getSubjectId() != 3;
                    }
                    // 数一和数三包含所有知识点
                    return true;
                })
                .collect(Collectors.toList());
    }

    @Override
    public QuestionDetailVO getQuestionDetail(Long questionId) {
        // 1. 获取题目基本信息（添加空检查）
        QuestionInfo questionInfo = userMockMapper.selectQuestionsByIds(Collections.singletonList(questionId))
                .stream()
                .findFirst()
                .orElseThrow(() -> new BusinessException("题目不存在或未关联到考试中，ID: " + questionId));

        // 2. 构建详情VO
        QuestionDetailVO detailVO = new QuestionDetailVO();
        BeanUtils.copyProperties(questionInfo, detailVO);

        // 3. 根据题型补充详情（添加空检查）
        switch (questionInfo.getQuestionType()) {
            // 在ExamServiceImpl.java的getQuestionDetail方法中，替换single_choice部分：

// 在ExamServiceImpl.java的getQuestionDetail方法中，替换single_choice部分：
            case "single_choice":
                ChoiceQuestion choiceQuestion = userMockMapper.selectChoiceByQuestionId(questionId);
                if (choiceQuestion == null) {
                    logger.warn("选择题详情不存在，题目ID: {}", questionId);
                    Map<String, String> defaultOptions = new LinkedHashMap<>();
                    defaultOptions.put("A", "选项A");
                    defaultOptions.put("B", "选项B");
                    defaultOptions.put("C", "选项C");
                    defaultOptions.put("D", "选项D");
                    detailVO.setOptionsMap(defaultOptions);
                    detailVO.setAnswer("A");
                    break;
                }

                // 调试日志：打印原始选项数据
                logger.info("题目ID: {}, 原始选项数据: {}", questionId, choiceQuestion.getOptions());

                Map<String, String> optionsMap = new LinkedHashMap<>();
                try {
                    String optionsStr = choiceQuestion.getOptions();
                    if (optionsStr == null || optionsStr.trim().isEmpty()) {
                        throw new RuntimeException("选项数据为空");
                    }

                    if (optionsStr.startsWith("[")) {
                        // JSON数组格式: ["(A) 内容", "(B) 内容", "(C) 内容", "(D) 内容"]
                        List<String> optionsList = JSON.parseArray(optionsStr, String.class);
                        for (String option : optionsList) {
                            if (option != null && option.length() >= 4 && option.startsWith("(") && option.charAt(2) == ')') {
                                // 提取选项标签和内容：从 "(A) 内容" 中提取 "A" 和 "内容"
                                String key = String.valueOf(option.charAt(1)); // 获取A、B、C、D
                                String value = option.substring(4).trim(); // 获取选项内容（跳过"(A) "）
                                optionsMap.put(key, value);
                            } else {
                                // 如果格式不匹配，按顺序分配A、B、C、D
                                char optionChar = (char)('A' + optionsMap.size());
                                optionsMap.put(String.valueOf(optionChar), option);
                            }
                        }
                    } else if (optionsStr.startsWith("{")) {
                        // JSON对象格式: {"A": "内容", "B": "内容", "C": "内容", "D": "内容"}
                        try {
                            optionsMap = JSON.parseObject(optionsStr, new TypeReference<LinkedHashMap<String, String>>(){});
                        } catch (Exception jsonError) {
                            logger.error("JSON对象解析失败，尝试手动解析: {}", jsonError.getMessage());
                            // 手动解析JSON对象（简单的正则匹配方式）
                            optionsMap = parseOptionsManually(optionsStr);
                        }
                    } else {
                        // 其他格式，尝试按分隔符解析
                        logger.warn("未知的选项格式，尝试按分隔符解析: {}", optionsStr);
                        String[] options = optionsStr.split("[|;,]");
                        char optionChar = 'A';
                        for (String option : options) {
                            if (option.trim().length() > 0) {
                                optionsMap.put(String.valueOf(optionChar), option.trim());
                                optionChar++;
                            }
                        }
                    }

                    if (optionsMap.isEmpty()) {
                        throw new RuntimeException("解析后选项为空");
                    }

                    logger.info("题目ID: {}, 解析后选项: {}", questionId, optionsMap);

                } catch (Exception e) {
                    logger.error("选项解析失败，题目ID: {}, 原始数据: {}, 错误: {}",
                            questionId, choiceQuestion.getOptions(), e.getMessage(), e);

                    // 解析失败时使用默认选项
                    optionsMap.clear();
                    optionsMap.put("A", "选项A");
                    optionsMap.put("B", "选项B");
                    optionsMap.put("C", "选项C");
                    optionsMap.put("D", "选项D");
                }

                detailVO.setOptionsMap(optionsMap);
                detailVO.setAnswer(choiceQuestion.getAnswer());
                break;

            case "fill_in_the_blank":
                FillBlankQuestion fillBlankQuestion = userMockMapper.selectFillBlankByQuestionId(questionId);
                if (fillBlankQuestion == null) {
                    logger.warn("填空题详情不存在，使用默认值，题目ID: {}", questionId);
                    detailVO.setAnswerTemplate("填空答案未录入");
                    break;
                }
                detailVO.setAnswerTemplate(fillBlankQuestion.getAnswerTemplate());
                break;

            case "subjective":
                SubjectiveQuestion subjectiveQuestion = userMockMapper.selectSubjectiveByQuestionId(questionId);
                if (subjectiveQuestion == null) {
                    logger.warn("主观题详情不存在，使用默认值，题目ID: {}", questionId);
                    subjectiveQuestion = new SubjectiveQuestion();
                    subjectiveQuestion.setReferenceAnswer("参考答案未录入");
                    subjectiveQuestion.setAnswerHints("解题提示未录入");
                }
                detailVO.setReferenceAnswer(subjectiveQuestion.getReferenceAnswer());
                detailVO.setAnswerHints(subjectiveQuestion.getAnswerHints());
                break;

            default:
                throw new BusinessException("未知题型: " + questionInfo.getQuestionType());
        }

        return detailVO;
    }

    @Override
    @Transactional
    public ExamResultVO submitExam(ExamSubmitDTO examSubmitDTO, Long userId) {
        // 1. 保存考试基本信息到 mock_exams 表
        MockExam mockExam = new MockExam();
        mockExam.setUserId(userId);
        mockExam.setExamType(examSubmitDTO.getExamType());
        mockExam.setExamStrategy(examSubmitDTO.getExamStrategy());
        mockExam.setTotalQuestions(examSubmitDTO.getQuestions().size());
        mockExam.setTotalTime(examSubmitDTO.getTotalTime() != null ? examSubmitDTO.getTotalTime() : 180);
        mockExam.setScore(0.0); // 初始分数设为0
        mockExam.setExamDate(new Date()); // 新增：记录当前日期
        userMockMapper.insertMockExam(mockExam);

        // 2. 计算得分并保存答题情况
        double totalScore = 0.0;
        int correctCount = 0;
        int wrongCount = 0;
        double choiceScore = 0.0;
        double fillBlankScore = 0.0;

        for (QuestionAnswerDTO questionAnswer : examSubmitDTO.getQuestions()) {
            Long questionId = questionAnswer.getQuestionId();
            String questionType = userMockMapper.getQuestionTypeById(questionId);

            // 初始化变量
            boolean isCorrect = false;
            double score = 0.0;
            String correctAnswer = "";

            // 只对客观题进行评分
            if ("single_choice".equals(questionType) || "fill_in_the_blank".equals(questionType)) {
                // 获取正确答案
                if ("single_choice".equals(questionType)) {
                    correctAnswer = userMockMapper.getChoiceQuestionAnswer(questionId);
                } else if ("fill_in_the_blank".equals(questionType)) {
                    correctAnswer = userMockMapper.getFillBlankQuestionAnswer(questionId);
                }

                // 判断答案是否正确
                isCorrect = correctAnswer != null && correctAnswer.equalsIgnoreCase(questionAnswer.getUserAnswer());
                score = isCorrect ? 5.0 : 0.0; // 每题5分

                // 累加分数
                if ("single_choice".equals(questionType)) {
                    choiceScore += score;
                } else {
                    fillBlankScore += score;
                }

                totalScore += score;

                if (isCorrect) {
                    correctCount++;
                } else {
                    wrongCount++;
                }
            } else {
                // 主观题不计分
                isCorrect = false;
                score = 0.0;
            }

            // 保存考试题目记录
            ExamQuestion examQuestion = new ExamQuestion();
            examQuestion.setExamId(mockExam.getExamId());
            examQuestion.setQuestionId(questionId);
            examQuestion.setUserAnswer(questionAnswer.getUserAnswer());
            examQuestion.setIsCorrect(isCorrect);
            examQuestion.setSequence(questionAnswer.getSequence());
            examQuestion.setQuestionType(questionType);
            examQuestion.setScore(score);
            userMockMapper.insertExamQuestion(examQuestion);


            // 只对客观题记录错题
            if (!isCorrect && !"subjective".equals(questionType)) {
                WrongQuestion wrongQuestion = new WrongQuestion();
                wrongQuestion.setUserId(userId);
                wrongQuestion.setQuestionId(questionId);
                wrongQuestion.setWrongCount(1);
                Integer subjectId = userMockMapper.getSubjectIdFromQuestions(questionId);
                if (subjectId != null) {
                    wrongQuestion.setSubjectId(subjectId);
                }
                userMockMapper.insertOrUpdateWrongQuestion(wrongQuestion);
            }
        }

        // 3. 更新考试总分
        mockExam.setScore(totalScore);
        mockExam.setCorrectQuestions(correctCount); // 新增：记录正确题数
        userMockMapper.updateMockExam(mockExam); // 需要修改Mapper方法支持更新更多字段

        // 4. 返回结果
        ExamResultVO resultVO = new ExamResultVO();
        resultVO.setExamId(mockExam.getExamId());  // 智能组卷设置examId
        resultVO.setTotalScore(totalScore);
        resultVO.setCorrectCount(correctCount);
        resultVO.setWrongCount(wrongCount);
        return resultVO;
    }

    // --------------------- 新增：分题型查询答案的 Mapper 方法调用 ---------------------
    // 假设 UserMockMapper 中已定义以下方法：
    // 1. 选择题：根据题目ID查询答案
    // String selectChoiceQuestionAnswer(@Param("questionId") Long questionId);

    // 2. 填空题：根据题目ID查询答案模板（返回 FillBlankQuestion 对象）
    // FillBlankQuestion selectFillBlankQuestionAnswer(@Param("questionId") Long questionId);

    // 3. 主观题：根据题目ID查询参考答案
    // String selectSubjectiveQuestionAnswer(@Param("questionId") Long questionId);
    @Override
    public ExamPaperVO getExamPaperByExamId(Long examId) {
        // 1. 获取考试基本信息
        MockExam exam = userMockMapper.selectMockExamById(examId);
        if (exam == null) {
            throw new BusinessException("考试不存在");
        }

        // 2. 获取考试关联的题目ID列表
        List<Long> questionIds = userMockMapper.selectQuestionIdsByExamId(examId);

        // 3. 批量获取题目详情
        List<QuestionDetailVO> questions = questionIds.stream()
                .map(this::getQuestionDetail)
                .collect(Collectors.toList());

        return new ExamPaperVO(exam, questions);
    }
    /**
     * 根据考试ID获取考试详情
     * @param examId 考试ID
     * @return 包含考试信息和题目详情的Map
     */
    @Override
    public Map<String, Object> getExamDetail(Long examId) {
        Map<String, Object> result = new HashMap<>();

        // 1. 查询考试基本信息
        MockExam mockExam = userMockMapper.selectMockExamById(examId);
        if (mockExam == null) {
            throw new RuntimeException("考试记录不存在，examId: " + examId);
        }
        result.put("examInfo", mockExam);

        // 2. 查询考试关联的题目ID列表
        List<Long> questionIds = userMockMapper.selectQuestionIdsByExamId(examId);

        // 3. 批量获取题目详情（包括用户作答情况）
        List<QuestionDetailVO> questions = questionIds.stream()
                .map(questionId -> {
                    // 获取题目基本信息
                    QuestionInfo questionInfo = userMockMapper.selectQuestionsByIds(Collections.singletonList(questionId))
                            .stream()
                            .findFirst()
                            .orElseThrow(() -> new BusinessException("题目不存在"));

                    // 获取用户作答情况
                    ExamQuestion examQuestion = userMockMapper.getExamQuestionByExamAndQuestion(examId, questionId);

                    // 构建详情VO
                    QuestionDetailVO detailVO = new QuestionDetailVO();
                    BeanUtils.copyProperties(questionInfo, detailVO);

                    // 设置作答情况
                    if (examQuestion != null) {
                        detailVO.setUserAnswer(examQuestion.getUserAnswer());
                        detailVO.setIsCorrect(examQuestion.getIsCorrect());
                        detailVO.setScore(examQuestion.getScore());
                    }

                    return detailVO;
                })
                .collect(Collectors.toList());

        result.put("questions", questions);

        return result;
    }
    /**
     * 按题型补足题目
     */
    private void supplementByType(
            List<QuestionInfo> current,
            Map<String, List<QuestionInfo>> typedQuestions,
            String type,
            int neededCount
    ) {
        if (neededCount <= 0) return;
        List<QuestionInfo> typeList = typedQuestions.getOrDefault(type, new ArrayList<>());
        int supplementCount = Math.min(neededCount, typeList.size());
        if (supplementCount > 0) {
            current.addAll(typeList.subList(0, supplementCount));
        }
    }
    /**
     * 按题型补足题目并添加到总列表（保持题型区块顺序）
     */
    private void supplementQuestionsByType(
            List<QuestionInfo> allQuestions,
            List<QuestionInfo> currentQuestions,
            String questionType,
            int targetCount,
            List<Integer> subjectIds,
            int typeId) {

        // 添加已有题目
        allQuestions.addAll(currentQuestions);

        // 计算需要补足的数量
        int needed = targetCount - currentQuestions.size();
        if (needed > 0) {
            List<QuestionInfo> supplemental = userMockMapper.findRandomQuestionsBySubjectAndType(
                    subjectIds, questionType, needed, typeId);

            // 确保补足的题目不会为null
            if (supplemental != null) {
                allQuestions.addAll(supplemental);
            }

            logger.warn("{} 题型补足了 {} 道题目", questionType, needed);
        }
    }

    //-----------------------------------------------------------------------------
    //------------------------------历年套卷---------------------------------------------
    //-------------------------------------------------------------------------------------
    @Override
    public List<PastExamRecord> getPastExamRecords(String examType, int year) {
        // 获取指定年份和类型的历年套卷记录
        List<PastExamRecord> records = userMockMapper.getPastExamRecordsByTypeAndYear(examType, year);

        // 按年份降序排序
        records.sort((r1, r2) -> r2.getExamYear() - r1.getExamYear());

        return records;
    }


    @Override
    public List<PastExamStat> getPastExamStats(Integer year) {
        // 获取统计数据
        List<PastExamStat> stats = userMockMapper.getPastExamStats(year);

        // 按年份降序排序
        stats.sort((s1, s2) -> s2.getExamYear() - s1.getExamYear());

        return stats;
    }
    @Override
    public List<QuestionInfo> getPastExamQuestions(String examType, int year) {
        return userMockMapper.getPastExamQuestions(examType, year);
    }

    // ExamServiceImpl.java

    @Override
    public List<PastExamPaper> getAllPastExamPapers() {
        try {
            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            List<Integer> years = IntStream.range(currentYear - 4, currentYear + 1)
                    .boxed()
                    .collect(Collectors.toList());

            List<PastExamPaper> papers = new ArrayList<>();
            List<String> examTypes = Arrays.asList("数一", "数二", "数三");

            for (int year : years) {
                for (String type : examTypes) {
                    try {
                        int count = userMockMapper.countPastExamQuestions(type, year);
                        if (count > 0) {
                            PastExamPaper paper = new PastExamPaper();
                            paper.setExamYear(year);
                            paper.setExamType(type);
                            paper.setTotalQuestions(count);
                            papers.add(paper);
                        }
                    } catch (Exception e) {
                        logger.error("统计历年套卷题目数量失败 - 类型: {}, 年份: {}", type, year, e);
                        // 继续处理其他数据
                    }
                }
            }

            papers.sort((p1, p2) -> p2.getExamYear() - p1.getExamYear());
            return papers;
        } catch (Exception e) {
            logger.error("获取历年套卷失败", e);
            return Collections.emptyList();
        }
    }

    // ExamServiceImpl.java 中添加

    @Override
    @Transactional
    public ExamResultVO submitPastExam(ExamSubmitDTO examSubmitDTO, Long userId) {
        // 1. 创建历年真题考试记录
        PastExamRecord pastExamRecord = new PastExamRecord();
        pastExamRecord.setUserId(userId);
        pastExamRecord.setUsername(null); // username允许为null
        pastExamRecord.setExamType(examSubmitDTO.getExamType());
        pastExamRecord.setExamYear(examSubmitDTO.getExamYear());
        pastExamRecord.setExamDate(new Date());
        pastExamRecord.setTotalQuestions(examSubmitDTO.getQuestions().size());
        pastExamRecord.setCorrectQuestions(0); // 初始化为0
        pastExamRecord.setScore(0.0); // 初始分数设为0
        pastExamRecord.setTotalTime(examSubmitDTO.getTotalTime() != null ? examSubmitDTO.getTotalTime() : 180);

        // 插入考试记录
        userMockMapper.insertPastExamRecord(pastExamRecord);
        Long recordId = pastExamRecord.getRecordId();

        // 2. 处理每个题目
        int correctCount = 0;
        double choiceScore = 0.0;
        double fillBlankScore = 0.0;

        for (QuestionAnswerDTO questionAnswer : examSubmitDTO.getQuestions()) {
            PastExamQuestion pastExamQuestion = new PastExamQuestion();
            pastExamQuestion.setRecordId(recordId);
            pastExamQuestion.setQuestionId(questionAnswer.getQuestionId());
            pastExamQuestion.setUserAnswer(questionAnswer.getUserAnswer());
            pastExamQuestion.setSequence(questionAnswer.getSequence());
            pastExamQuestion.setQuestionType(questionAnswer.getQuestionType());

            // 只对客观题(选择题和填空题)进行评分
            if ("single_choice".equals(questionAnswer.getQuestionType()) ||
                    "fill_in_the_blank".equals(questionAnswer.getQuestionType())) {
                String correctAnswer = getCorrectAnswer(questionAnswer);
                boolean isCorrect = correctAnswer != null &&
                        correctAnswer.equalsIgnoreCase(questionAnswer.getUserAnswer());
                pastExamQuestion.setIsCorrect(isCorrect);

                if (isCorrect) {
                    correctCount++;
                    double questionScore = 5.0; // 每题5分

                    if ("single_choice".equals(questionAnswer.getQuestionType())) {
                        choiceScore += questionScore;
                    } else {
                        fillBlankScore += questionScore;
                    }
                }
            } else {
                // 主观题不判分
                pastExamQuestion.setIsCorrect(null);
            }

            userMockMapper.insertPastExamQuestion(pastExamQuestion);
        }

        // 3. 更新考试统计信息
        double totalScore = choiceScore + fillBlankScore;
        pastExamRecord.setCorrectQuestions(correctCount);
        pastExamRecord.setScore(totalScore);
        userMockMapper.updatePastExamRecord(pastExamRecord);

        // 4. 返回结果
        ExamResultVO resultVO = new ExamResultVO();
        resultVO.setRecordId(recordId);
        resultVO.setTotalScore(totalScore);
        resultVO.setCorrectCount(correctCount);
        resultVO.setWrongCount(examSubmitDTO.getQuestions().size() - correctCount);
        resultVO.setChoiceScore(choiceScore);
        resultVO.setFillBlankScore(fillBlankScore);
        return resultVO;
    }
    private double calculateScore(int correctCount, int totalQuestions) {
        // 简单计算分数逻辑，可根据实际需求调整
        return (correctCount * 100.0) / totalQuestions;
    }

    // 辅助方法：获取正确答案
    private String getCorrectAnswer(QuestionAnswerDTO question) {
        if (question == null) {
            return null;
        }
        return getQuestionCorrectAnswer(question.getQuestionId(), question.getQuestionType());
    }
    // 修改 getPastExamDetail 方法
    @Override
    public Map<String, Object> getPastExamDetail(Long recordId) {
        Map<String, Object> result = new HashMap<>();

        // 1. 获取考试记录
        PastExamRecord record = userMockMapper.selectPastExamRecordById(recordId);
        if (record == null) {
            throw new BusinessException("考试记录不存在");
        }
        result.put("examInfo", record);

        // 2. 获取题目详情（带正确答案）
        List<PastExamQuestion> examQuestions = userMockMapper.selectPastExamQuestionsByRecordId(recordId);
        List<Map<String, Object>> questionsWithAnswers = examQuestions.stream()
                .map(q -> {
                    Map<String, Object> detail = new HashMap<>();
                    detail.put("questionId", q.getQuestionId());
                    detail.put("userAnswer", q.getUserAnswer());
                    detail.put("isCorrect", q.getIsCorrect());
                    detail.put("sequence", q.getSequence());

                    // 获取题目类型
                    String questionType = userMockMapper.getQuestionTypeById(q.getQuestionId());
                    detail.put("questionType", questionType);

                    // 获取题目内容
                    QuestionInfo questionInfo = userMockMapper.selectQuestionById(q.getQuestionId());
                    if (questionInfo != null) {
                        detail.put("content", questionInfo.getContent());
                    }

                    // 使用正确的方法获取答案
                    detail.put("correctAnswer",
                            userMockMapper.getCorrectAnswerByType(q.getQuestionId(), questionType));

                    return detail;
                })
                .collect(Collectors.toList());

        result.put("questions", questionsWithAnswers);
        return result;
    }
    // 新增统一答案查询方法
    private String getQuestionCorrectAnswer(Long questionId, String questionType) {
        if (questionId == null || questionType == null) {
            return null;
        }

        switch (questionType) {
            case "single_choice":
                ChoiceQuestion choice = userMockMapper.selectChoiceByQuestionId(questionId);
                return choice != null ? choice.getAnswer() : null;
            case "fill_in_the_blank":
                FillBlankQuestion fillBlank = userMockMapper.selectFillBlankByQuestionId(questionId);
                return fillBlank != null ? fillBlank.getAnswerTemplate() : null;
            case "subjective":
                SubjectiveQuestion subjective = userMockMapper.selectSubjectiveByQuestionId(questionId);
                return subjective != null ? subjective.getReferenceAnswer() : null;
            default:
                return null;
        }
    }
    // 在ExamServiceImpl类中添加这个辅助方法：
    private Map<String, String> parseOptionsManually(String optionsStr) {
        Map<String, String> optionsMap = new LinkedHashMap<>();
        try {
            // 移除首尾的花括号
            String content = optionsStr.substring(1, optionsStr.length() - 1);

            // 按照 "," 分割，但要考虑引号内的逗号
            List<String> pairs = new ArrayList<>();
            boolean inQuotes = false;
            StringBuilder currentPair = new StringBuilder();

            for (int i = 0; i < content.length(); i++) {
                char c = content.charAt(i);
                if (c == '"' && (i == 0 || content.charAt(i - 1) != '\\')) {
                    inQuotes = !inQuotes;
                    currentPair.append(c);
                } else if (c == ',' && !inQuotes) {
                    pairs.add(currentPair.toString().trim());
                    currentPair = new StringBuilder();
                } else {
                    currentPair.append(c);
                }
            }
            if (currentPair.length() > 0) {
                pairs.add(currentPair.toString().trim());
            }

            // 解析每个键值对
            for (String pair : pairs) {
                int colonIndex = pair.indexOf(':');
                if (colonIndex > 0) {
                    String key = pair.substring(0, colonIndex).trim().replaceAll("^\"|\"$", "");
                    String value = pair.substring(colonIndex + 1).trim().replaceAll("^\"|\"$", "");
                    optionsMap.put(key, value);
                }
            }

            return optionsMap;
        } catch (Exception e) {
            logger.error("手动解析选项失败: {}", e.getMessage());
            // 返回默认选项
            Map<String, String> defaultOptions = new LinkedHashMap<>();
            defaultOptions.put("A", "选项A");
            defaultOptions.put("B", "选项B");
            defaultOptions.put("C", "选项C");
            defaultOptions.put("D", "选项D");
            return defaultOptions;
        }
    }



}